/****************************************************************
 * A class made to return the amount of work(Watt) used by a heatpump
 * to maintain a temperature, based upon the temperature inside and outside
 * the building, and the heatloss through surfaces (Surface.java)
 ****************************************************************/


package simulator.engine;

import java.util.ArrayList;

/**
 * @author Sigurd W. Aspen, Modifisert Kim Rune Solstad
 * 
 * computeWork() er den eneste klassen som trenger å brukes
 * den tar foreløpig bare å kalkulerer hvor mye energi som brukes
 * for å opprettholde en temperatur i et rom som bare har varmetap 
 * fra en vegg, skal gjøres om til å kalkulere for en liste med vegger.
 */
public class HeatPump 
{
    private ArrayList<Surface> surfaces;
    
    public HeatPump(ArrayList<Surface> surface)
    {
        surfaces = surface;
    }
    
    //Mainen er bare for testing
    public static void main(String[] args) throws Exception{
        
        
        ArrayList<Surface> surface = new ArrayList<Surface>();
        surface.add(new Surface(8000, 2000, 0.46));
        surface.add(new Surface(6000, 2000, 0.46));
        surface.add(new Surface(8000, 6000, 0.49));
        HeatPump hp = new HeatPump(surface);
        
        System.out.println((hp.computeWork(35, 0, surface)));
    }
    
    /**
     * A number used to get a realistic Coeffiecent of performance out off the theoretical maximum
     * used in the getCop() method
     */
    private static final double copReducer = 2.5;

    
    /**
     * @param tempInside inne i bygningen
     * @param tempOutside utenfor bygningen
     * @param surface acess to a surface object to get building properties
     * @return the amount of work(Watt) needed to keep the temperature
     */
    public double computeWork(double tempInside, double tempOutside, ArrayList<Surface> surface){
        double watt = 0;
        for(Surface i : surface){
            watt += i.computeHeatLoss(tempInside, tempOutside);
        }
        watt /= getCOP(tempInside, tempOutside);
        return watt;
    }
    
    public double computeWork(double tempInside, double tempOutside)
    {
        double watt = 0;
        for(Surface i : surfaces)
            watt += i.computeHeatLoss(tempInside, tempOutside);
        
        watt /= getCOP(tempInside, tempOutside);
        return watt;
    }
    
    /**
     * @param tempInside temperature inside the building
     * @param tempOutside temperature outside the building
     * @return the teorethical maximum coefficient of performance for the heat pump
     * 
     */
    private double getCOP(double tempInside, double tempOutside){
        //Cooling
        if(tempInside < tempOutside){
             return (convertToKelvin(tempOutside) / (convertToKelvin(tempOutside) - convertToKelvin(tempInside))) / copReducer - 1;
        }
        //Heating
        else if (tempInside > tempOutside){
             return (convertToKelvin(tempInside) / (convertToKelvin(tempInside) - convertToKelvin(tempOutside))) / copReducer;
        }
        return 0;
    }

    /**
     * @param celcius the temperature in celcius
     * @return the temperature in kelvin
     */
    private double convertToKelvin(double celcius){
        return celcius + 273.15;
    }
}
